package com.booking.springrestful.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.booking.springrestful.domain.*;
import com.booking.springrestful.domain.dto.CounselorsDto;
import com.booking.springrestful.domain.dto.CounselorsSaveDto;
import com.booking.springrestful.domain.dto.upVo;
import com.booking.springrestful.domain.vo.CounselorsUpVo;
import com.booking.springrestful.domain.vo.CounselorsVo;
import com.booking.springrestful.exception.BusinessException;
import com.booking.springrestful.mapper.*;
import com.booking.springrestful.resp.PageResult;
import com.booking.springrestful.resp.ResultCodeEnum;
import com.booking.springrestful.service.CounselorsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
* @author 13182
* @description 针对表【counselors】的数据库操作Service实现
* @createDate 2024-10-31 22:15:36
*/
@Service
@Slf4j
public class CounselorsServiceImpl extends ServiceImpl<CounselorsMapper, Counselors>
    implements CounselorsService {

    @Resource
    private UsersMapper usersMapper;

    @Resource
    private CounselorscheduleMapper counselorscheduleMapper;

    @Resource
    private CounselorsMapper counselorsMapper;


    @Resource
    private ConsultationroomMapper consultationroomMapper;


    @Resource
    private TimeslotMapper timeslotMapper;

    @Override
    public PageResult<CounselorsVo> getCounselor(CounselorsDto counselorsDto) {

        //根据评分排序
        QueryWrapper<Counselors> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("rating");

        String specialty = counselorsDto.getSpecialty();
        if (StringUtils.isNotBlank(specialty)){
            wrapper.eq("specialty",specialty);
        }

        String room = counselorsDto.getRoom();


        if (StringUtils.isNotBlank(room)){
            //先找出所有的工作时间匹配当前的咨询室
            List<Counselorschedule> roomList = counselorscheduleMapper.selectList(new QueryWrapper<Counselorschedule>().eq("room", room));
            ArrayList<Integer> idList = new ArrayList<>();
            roomList.forEach(item->{
                idList.add(item.getCounselorid());
            });
            log.info(idList.toString());
            if (!idList.isEmpty()){
                wrapper.in("counselorId",idList);
            }else {
                wrapper.eq("counselorId",0);
            }

        }

        String status = counselorsDto.getStatus();
        if (StringUtils.isNotBlank(status)){
            wrapper.eq("status",status);
        }
        wrapper.orderByDesc("updatedAt");

        long pageSize = counselorsDto.getPageSize();
        long current = counselorsDto.getCurrent();

        IPage<Counselors> page = new Page<>(current, pageSize); // 创建分页对象

        // 进行分页查询
        IPage<Counselors> resultPage = counselorsMapper.selectPage(page, wrapper);

        log.info(resultPage.getRecords().toString());

        // 创建一个新的 IPage 对象，泛型为 CounselorsVo
        IPage<CounselorsVo> voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal());
        List<CounselorsVo> voRecords = new ArrayList<>();

        resultPage.getRecords().forEach(record -> {
            // 在循环中处理每条记录，并转换为 CounselorsVo
            CounselorsVo vo = new CounselorsVo();

            Users user = usersMapper.selectOne(new QueryWrapper<Users>().eq("userId", record.getUserid()));
            BeanUtils.copyProperties(user, vo);
            BeanUtils.copyProperties(record, vo);

            voRecords.add(vo);
        });

        voPage.setRecords(voRecords);

        // 创建包含数据和分页信息的对象
        PageResult<CounselorsVo> pageResult = new PageResult<>();
        pageResult.setTotal(voPage.getTotal());
        pageResult.setData(voPage.getRecords());
        return pageResult;
    }

    @Override
    public List<CounselorsVo> getUsername() {

        List<Users> users = usersMapper.selectList(new QueryWrapper<Users>().eq("userType", "counselor").eq("status",'1'));
        ArrayList<CounselorsVo> list = new ArrayList<>();

        users.forEach(item->{
            if (!counselorsMapper.exists(new QueryWrapper<Counselors>().eq("userId",item.getUserid()))){
                CounselorsVo vo = new CounselorsVo();
                vo.setUsername(item.getUsername());
                vo.setRealname(item.getRealname());
                list.add(vo);
            }
        });

        return list;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delCounselor(List<CounselorsVo> counselorsVos, String msg) {
        counselorsVos.forEach(item->{
            if (counselorsMapper.exists(new QueryWrapper<Counselors>().eq("userId",item.getUserid()).eq("status",'1'))){
                throw new BusinessException(ResultCodeEnum.INTERNAL_SERVER_ERROR,msg);
            }
            if(counselorsMapper.exists(new QueryWrapper<Counselors>().eq("userId",item.getUserid()))){
                counselorsMapper.delete(new QueryWrapper<Counselors>().eq("userId",item.getUserid()));
            }
            if (counselorscheduleMapper.exists(new QueryWrapper<Counselorschedule>().eq("counselorId",item.getCounselorId()))){
                counselorscheduleMapper.delete(new QueryWrapper<Counselorschedule>().eq("counselorId",item.getCounselorId()));
            }
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class) // 当抛出Exception及其子类时回滚
    public void saveCounselor(CounselorsSaveDto counselorsSaveDto) {
        log.info(counselorsSaveDto.toString());
        String username = counselorsSaveDto.getUsername();
        Integer userid = usersMapper.selectOne(new QueryWrapper<Users>().eq("username", username)).getUserid();
        //插入咨询师信息表
        Counselors counselors = new Counselors();
        BeanUtils.copyProperties(counselorsSaveDto,counselors);
        counselors.setUserid(userid);
        counselorsMapper.insert(counselors);

        Integer id = counselorsMapper.selectOne(new QueryWrapper<Counselors>().eq("userid", userid)).getCounselorid();

        //插入咨询师工作时间表
        List<Counselorschedule> list = counselorsSaveDto.getCounselorscheduleList();
        //检查是否在咨询室范围内
        checkRoom(list);
        if (!list.isEmpty()){
            //检查重叠
            checkTimeOverlap(list,"时间段重叠");

            //检查系统数据重叠
            //先查询所有时间段
            List<Counselorschedule> availableList = counselorscheduleMapper.selectList(null);

            availableList.addAll(list);
            //检查所有
            checkTimeOverlap(availableList,"与其他咨询师时间段冲突");

            list.forEach(item->{
                Counselorschedule counselorschedule = new Counselorschedule();
                BeanUtils.copyProperties(item,counselorschedule);
                counselorschedule.setCounselorid(id);
                counselorscheduleMapper.insert(counselorschedule);
            });
        }

    }

    @Override
    public CounselorsUpVo getByUserId(Integer userId) {

        Counselors selectOne = counselorsMapper.selectOne(new QueryWrapper<Counselors>().eq("userId", userId));
        CounselorsUpVo dto = new CounselorsUpVo();
        BeanUtils.copyProperties(selectOne,dto);
        String username = usersMapper.selectOne(new QueryWrapper<Users>().eq("userId", userId)).getUsername();
        dto.setUsername(username);

        //查询工作时间
        List<Counselorschedule> list = counselorscheduleMapper.selectList(new QueryWrapper<Counselorschedule>().eq("counselorId", selectOne.getCounselorid()));

        ArrayList<upVo> upList = new ArrayList<>();
        list.forEach(item->{
            upVo upVo = new upVo();
            upVo.setRoom(item.getRoom());
            upVo.setWeekend(item.getWeekend());
            upVo.setStarttime(item.getStarttime().toString());
            upVo.setEndtime(item.getEndtime().toString());
            upList.add(upVo);
        });

        dto.setCounselorscheduleList(upList);
        return dto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class) // 当抛出Exception及其子类时回滚
    public void upCounselor(CounselorsSaveDto counselorsSaveDto) {

        List<Counselorschedule> list = counselorsSaveDto.getCounselorscheduleList();

        //检查是否在咨询室范围内
        checkRoom(list);


        //检查时间

        checkTimeOverlap(list,"时间段重叠");


        //先删除
        Integer userid = usersMapper.selectOne(new QueryWrapper<Users>().eq("username", counselorsSaveDto.getUsername())).getUserid();
        Counselors counselors = counselorsMapper.selectOne(new QueryWrapper<Counselors>().eq("userId", userid));
        counselorscheduleMapper.delete(new QueryWrapper<Counselorschedule>().eq("counselorId",counselors.getCounselorid()));


        List<Counselorschedule> availableList = counselorscheduleMapper.selectList(null);

        availableList.addAll(list);
        //检查所有
        checkTimeOverlap(availableList,"与其他咨询师时间段冲突");

        //然后增加
        //在当前用户id增加
        Counselors one = new Counselors();
        BeanUtils.copyProperties(counselorsSaveDto,one);
        one.setUserid(userid);

        counselorsMapper.update(one,new QueryWrapper<Counselors>().eq("userId",userid));

        Integer id = counselorsMapper.selectOne(new QueryWrapper<Counselors>().eq("userId", userid)).getCounselorid();

        counselorsSaveDto.getCounselorscheduleList().forEach(item->{
            Counselorschedule counselorschedule = new Counselorschedule();
            BeanUtils.copyProperties(item,counselorschedule);
            counselorschedule.setCounselorid(id);
            counselorschedule.setIsavailable(1);

            counselorscheduleMapper.insert(counselorschedule);
        });




    }

    private void checkRoom(List<Counselorschedule> list) {
        log.info("进入检查是否在咨询室范围内");
        log.info(list.toString());
        //检查是否在咨询室范围内
        list.forEach(item -> {
            Date starttime = item.getStarttime();
            Date endtime = item.getEndtime();

            // 计算时间差，单位为毫秒
            long durationInMillis = endtime.getTime() - starttime.getTime();
            // 将时间差转换为分钟
            long durationInMinutes = TimeUnit.MILLISECONDS.toMinutes(durationInMillis);

            // 校验时间范围：30分钟（包括）到90分钟（包括）
            if (durationInMinutes < 30 || durationInMinutes > 90) {
                throw new BusinessException(ResultCodeEnum.INTERNAL_SERVER_ERROR, "时间段只能在30分钟至90分钟");
            }



            String room = item.getRoom();
            log.info("获取当前咨询室");
            log.info(room);
            List<Consultationroom> roomList = consultationroomMapper.selectList(new QueryWrapper<Consultationroom>().eq("room", room));
            log.info("获取匹配的咨询室");
            log.info(roomList.toString());
            roomList.forEach(roomItem -> {
                //if (roomItem.getRoom().equals(room)) { // 使用 equals 方法比较字符串相等性
                    List<Timeslot> timeslotList = timeslotMapper.selectList(new QueryWrapper<Timeslot>().eq("consultationRoomId", roomItem.getConsultationRoomId()));
                    log.info("获取当前咨询室的时间段");
                    log.info(timeslotList.toString());
                    for (int i = 0; i < roomItem.getTimetotal(); i++) {
                        Date startTime = timeslotList.get(i).getStartTime();
                        Date endTime = timeslotList.get(i).getEndTime();

                        log.info("获取当前咨询室的时间段");
                        log.info(startTime.toString());
                        log.info(endTime.toString());

                        // 获取时分秒部分
                        LocalTime startLocalTime = LocalDateTime.ofInstant(startTime.toInstant(), ZoneId.systemDefault()).toLocalTime();
                        LocalTime endLocalTime = LocalDateTime.ofInstant(endTime.toInstant(), ZoneId.systemDefault()).toLocalTime();
                        LocalTime itemStartLocalTime = LocalDateTime.ofInstant(starttime.toInstant(), ZoneId.systemDefault()).toLocalTime();
                        LocalTime itemEndLocalTime = LocalDateTime.ofInstant(endtime.toInstant(), ZoneId.systemDefault()).toLocalTime();

                        // 检查上面的时间段是否完全在下面的时间段之内（边界允许相等）
                        if (itemStartLocalTime.isBefore(startLocalTime) || itemStartLocalTime.equals(startLocalTime)) {
                            if (itemEndLocalTime.isAfter(endLocalTime) || itemEndLocalTime.equals(endLocalTime)) {
                                // 如果上面的时间段不在下面的时间段之内
                                throw new BusinessException(ResultCodeEnum.INTERNAL_SERVER_ERROR, "不在咨询室开放时间范围内");
                            }
                        }
                    }
                //}
            });
        });
    }

    //转换时间段为字符串
    public static String formatTimeRange(Date startTime, Date endTime) {
        SimpleDateFormat sdf = new SimpleDateFormat("H:mm");

        String startTimeStr = sdf.format(startTime);
        String endTimeStr = sdf.format(endTime);

        return startTimeStr + " - " + endTimeStr;
    }





    private static final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");

    public void checkTimeOverlap(List<Counselorschedule> events,String msg) {
        for (int i = 0; i < events.size(); i++) {
            for (int j = i + 1; j < events.size(); j++) {
                Counselorschedule event1 = events.get(i);
                Counselorschedule event2 = events.get(j);

                String startTime1 = timeFormat.format(event1.getStarttime());
                String endTime1 = timeFormat.format(event1.getEndtime());
                String startTime2 = timeFormat.format(event2.getStarttime());
                String endTime2 = timeFormat.format(event2.getEndtime());

                if (Objects.equals(events.get(i).getWeekend(), events.get(j).getWeekend())&&Objects.equals(events.get(i).getRoom(), events.get(j).getRoom())){
                    if (startTime1.compareTo(endTime2) < 0 && endTime1.compareTo(startTime2) > 0) {
                        throw new BusinessException(ResultCodeEnum.INTERNAL_SERVER_ERROR, msg);
                    }

                }


            }
        }
    }

}




